#include <iostream>
#include <fstream>

#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
// static string strFileName ;
// static string strFileNameUpper;


int main(int argc, char const *argv[])
{
	static string outFileName ;
	char buffer[1024];

	cout << "!!!!!!!!!!!!!!!!!!!!!!" << endl;
	cout << "!!!tool by xiaoyong!!!" << endl;
	cout << "!!!!!!!!!!!!!!!!!!!!!!" << endl;
	if(argc < 2)
	{
		cout << "缺少参数" << endl;
		for (int i = 1; i < argc; i++)
		{
			cout << "argv-" << i << ' ' << argv[i] << endl;
		}
		return -1;
	}
	string inputFileName = argv[1];
	cout << "input file:" << inputFileName << endl;
	cv::Mat imgInput = cv::imread(inputFileName);
	if(imgInput.empty())
	{
		cout << "无法打开文件:" << inputFileName << endl;
		return 0;
	}

	//确定输出文件名
	if(argc > 2)
	{
		outFileName = argv[2];
		size_t found_dot = outFileName.find_last_of('.');
		if(found_dot == (size_t)-1)
		{
			outFileName += ".h";
		}
	}
	else
	{
		string str_path ;
		string str_name;
		size_t found_line = inputFileName.find_last_of('\\');
		size_t found_dot = inputFileName.find_last_of('.');
		if(found_dot > inputFileName.length())
		{
			found_dot = inputFileName.length();
		}
		if(found_line == (size_t)-1)
		{
			found_line = 0 ;
		}
		else
		{
			found_line += 1;
		}
		str_path = inputFileName.substr(0,found_line);
		str_name = inputFileName.substr(found_line,found_dot - found_line);
		outFileName = str_path + "pic_data_" + str_name + ".h";
	}

	int imgType = imgInput.type();

	cout << "image depth   : " ;
	switch (CV_MAT_DEPTH(imgType))
	{
	case CV_8U :
		cout << "8U" << endl;
	break;
	case CV_8S :
		cout << "8S" << endl;
	break;
	case CV_16U:
		cout << "16U" << endl;
	break;
	case CV_16S:
		cout << "16S" << endl;
	break;
	case CV_32S:
		cout << "32S" << endl;
	break;
	case CV_32F:
		cout << "32F" << endl;
	break;
	case CV_64F:
		cout << "64F" << endl;
	break;
	case CV_16F:
		cout << "16F" << endl;
	break;
	default:
		break;
	}
	cout << "image channel : " << (imgType >> CV_CN_SHIFT) + 1 << endl;
	cout << "image width   : " << imgInput.cols << endl;
	cout << "image height  : " << imgInput.rows << endl;

	cv::Mat imgBGR565 ;
	cv::cvtColor(imgInput,imgBGR565,cv::COLOR_BGR2BGR565);

	int w = imgBGR565.cols;
	int h = imgBGR565.rows;
	int max_pixel = w * h;

	if(max_pixel > 0)
	{
		const ushort *pIndex = (const ushort *)imgBGR565.ptr<const uchar>(0) ;
		int cnt = 0 ;
		ushort r,g,b;
		ushort c_bgr;
		ushort c_rgb;

		cout << "out file:" << outFileName << endl;
		ofstream outFile(outFileName,ios::binary | ios::out);
		if(!outFile)
		{
			cout << "connot create out file !!!" << endl ;
		}
		else
		{
			int l ;
			outFile.seekp(outFile.beg);

			size_t found_line = outFileName.find_last_of('\\');
			size_t found_dot = outFileName.find_last_of('.');
			if(found_dot == (size_t)-1)
			{
				found_dot = 0;
			}
			found_line += 1;

			string strFileName = outFileName.substr(found_line,found_dot-found_line);
			size_t j;
			for (j = 0; j < strFileName.length() && j < sizeof(buffer); j++)
			{
				buffer[j] = toupper(strFileName[j]);
			}
			buffer[j] = 0 ;
			string strFileNameUpper = buffer;
			l = sprintf(buffer,"#ifndef __%s_H\r\n#define __%s_H\r\n",strFileNameUpper.data(),strFileNameUpper.data());
			outFile.write(buffer,l);

			l = sprintf(buffer,"\r\n#define _W_%s %d\r\n",strFileNameUpper.data(),w);
			outFile.write(buffer,l);

			l = sprintf(buffer,"#define _H_%s %d\r\n",strFileNameUpper.data(),h);
			outFile.write(buffer,l);

			l = sprintf(buffer,"\r\nconst unsigned short %s[]={\r\n",strFileName.data());
			outFile.write(buffer,l);
			int colsBytes = w * 7;
			char *outBuffer = (char *)::malloc(colsBytes);
			if(outBuffer == NULL)
			{
				cout << "malloc error , bytes:" << colsBytes << endl;
				outFile.close();
				return 0;
			}
			char *colsBuffer = outBuffer;
			while(cnt < max_pixel)
			{
				c_bgr = *pIndex ++;
				r = (c_bgr & 0x001F) >> 0;
				g = (c_bgr & 0x07E0) >> 0;
				b = (c_bgr & 0xF800) >> 11;
				c_rgb = (r << 11) | g | b;
				l = sprintf(colsBuffer,"0x%04x,",c_rgb) ;
				colsBuffer += l;
				cnt ++;
				if((cnt % w) == 0)
				{
					outFile.write(outBuffer,colsBytes);//转换完一行后再写到文件中去
					outFile.write("\r\n",2);
					colsBuffer = outBuffer;
				}
			}
			::free(outBuffer);
			outFile.write("};\r\n\r\n#endif\r\n",14);
			outFile.close();
			cout << "convert done ^_^ " << endl;
		}
	}
	else
	{
		cout << "Data error !!!" << endl ;
	}
	// cv::imshow("rgb",imgInput);
	// cv::waitKey();
	return 0;
}
